#ifndef _MODULES_H_
#define _MODULES_H_
#include <QString>
#include <QStringList>
#include <QSharedPointer>
#include "CacheMap.h"

class QFileInfo;
struct _object;
typedef _object PyObject;
class CramBuilder;
class ModuleScope;
class SimpleNode;
class BinaryModule;
typedef QSharedPointer<SimpleNode> SimpleNodePtr;

typedef QHash<QString, QString> PropMap;

class Modules
{
public:
    Modules();
    virtual ~Modules();
    static Modules* getModules();
    static void end();

    ModuleScope* moduleByName(const QString& moduleName, const QString& relativePath = "", bool useCache = false);
    ModuleScope* moduleByFileName(const QString& fileName, bool useCache = false);

private:
    void setImportPathes();
    ModuleScope* _moduleByFileName(const PropMap& fileName, bool useCache = false);
    ModuleScope* addModuleByName(const QString& name, const QString& relativePath = "", bool useCache = false);

    ModuleScope* parsePythonFile(const PropMap& fi, bool useCache = true);
    ModuleScope* _pyParse(const QString& fileName);

    ModuleScope* importZipPythonPackage(const QFileInfo& fi);
    ModuleScope* importEggPackage(const QFileInfo& fi);
    ModuleScope* importPackage(const QFileInfo& fi);
    ModuleScope* importBinary(const PropMap& fi);

    void processScope(PyObject* obj, CramBuilder* builder, bool onlyPublic = false);
    PropMap fileNameByImport(const QString& name, const QString& relativePath = "");
    void restoreBootStrap(const SimpleNodePtr& root, CramBuilder* builder);
    BinaryModule *binary();
    QFileInfo findInPathes(const QString name, const QStringList& pathes);
private:
    static Modules* _instance;
    QMap<QString, ModuleScope*> _modulesCache;
    QStringList _importPathes;
    CacheMap _cacheMap;
    BinaryModule* _binary;
};

#endif
